<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8"/>
    <title>文档聚类结果</title>
    <script>    // 全局颜色数组
    const colors = ['#007BFF', '#28A745', '#DC3545', '#FFC107', '#6F42C1'];
    </script>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 40px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 900px;
            margin: auto;
        }
        .card {
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
            padding: 20px;
            margin-bottom: 30px;
        }
        .card h3 {
            color: #007BFF;
        }
        ul {
            list-style-type: none;
            padding-left: 0;
        }
        li {
            margin-bottom: 10px;
        }
        a {
            text-decoration: none;
            color: #007BFF;
        }
        .back-button {
            position: absolute;
            top: 20px;
            left: 20px;
            padding: 8px 12px;
            font-size: 14px;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        /* 控制面板样式 */
        .control-panel {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 20px;
            gap: 15px;
            flex-wrap: wrap;
        }
        .control-panel select,
        .control-panel button {
            font-size: 14px;
            padding: 6px 12px;
        }

        .loading-overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.5);
        z-index: 9999;
        justify-content: center;
        align-items: center;
    }

    .spinner {
        width: 50px;
        height: 50px;
        border: 5px solid #fff;
        border-top: 5px solid #007BFF;
        border-radius: 50%;
        animation: spin 1s linear infinite;
    }

    @keyframes spin {
        from { transform: rotate(0deg); }
        to { transform: rotate(360deg); }
    }

    .wordcloud {
        width: 100%;
        min-height: 200px;
        margin-top: 10px;
        border-radius: 8px;
        background-color: #f9f9f9;
        padding: 10px;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        overflow: hidden;
    }
    </style>
</head>
<body>

<div class="container">
    <div style="position: relative;">
        <!-- 返回首页按钮 -->
        <a href="/">
            <button style="padding: 8px 12px; font-size: 14px; background-color: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer;">
                ← 返回首页
            </button>
        </a>
        <h2 style="text-align: center;">文档聚类结果（前3个最大类）</h2>
    </div>

    <!-- 新增控制面板 -->
    <div class="control-panel">
        <label>
            语言：
            <select id="langSelect">
                <option value="cn" selected>中文</option>
                <option value="en">英文</option>
            </select>
        </label>

        <label>
            聚类数量：
            <select id="kSelect">
                <option value="5">5</option>
                <option value="10">10</option>
                <option value="20" selected>20</option>
                <option value="25">25</option>
                <option value="50">50</option>
            </select>
        </label>

        <!-- 加载聚类结果按钮 -->
        <button onclick="loadClusterResults()"
                style="padding: 8px 16px; font-size: 14px; background-color: #007BFF; color: white; border: none; border-radius: 4px; cursor: pointer;">
            加载聚类结果
        </button>
    </div>

    <!-- 聚类结果 + 词云 -->
    <div id="cluster-results"></div>
    <div id="wordcloud-container"></div>  <!-- 新增 -->
</div>
<!-- 柱状图容器 -->
<div id="bar-chart" style="width: 100%; height: 400px; margin-top: 30px;"></div>
<!-- 散点图容器 -->
<div id="scatter-chart" style="width: 100%; height: 600px; margin-top: 30px;"></div>

<!-- 加载动画组件 -->
<div class="loading-overlay" id="loadingOverlay">
    <div class="spinner"></div>
</div>


<!-- 替换后 -->
<script src="{{ url_for('static', filename='js/wordcloud2.js') }}"></script>
<script src="{{ url_for('static', filename='js/echarts.min.js') }}"></script>



<script>
function loadClusterResults() {
    const overlay = document.getElementById("loadingOverlay");
    overlay.style.display = "flex";

    const lang = document.getElementById("langSelect").value;
    const k = document.getElementById("kSelect").value;

    fetch(`/api/cluster?lang=${lang}&k=${k}`)
        .then(res => res.json())
        .then(data => {
            overlay.style.display = "none";
            if (data.error) {
                document.getElementById("cluster-results").innerHTML = `<p>${data.error}</p>`;
                return;
            }
            data.clusters.sort((a, b) => b.size - a.size);
            renderBarChart(data.clusters);
            // ✅ 拿到所有聚类 + embeddings 数据
            const clusters = data.clusters.slice(0, 3);
            const embeddings = data.embeddings;

            let html = "";

            clusters.forEach(cluster => {
                html += `
                    <div class="card">
                        <h3>类 ${cluster.cluster_id}（共 ${cluster.size} 篇）</h3>
                        <ul>
                `;

                cluster.docs.forEach(doc => {
                    html += `
                        <li>
                            <a href="/details?id=${doc.doc_id}" target="_blank">${doc.title}</a>
                            &nbsp;&nbsp;<small>余弦距离: ${doc.distance}</small>
                        </li>
                    `;
                });

                html += `
                        </ul>
                        <div class="wordcloud" id="wc-${cluster.cluster_id}"></div>
                    </div>
                `;
            });

            document.getElementById("cluster-results").innerHTML = html;

            // 渲染词云
            clusters.forEach(cluster => {
                const container = document.getElementById(`wc-${cluster.cluster_id}`);
                const list = cluster.centroid_keywords.map(k => [k.word, k.weight * 100]);
                WordCloud(container, {
                    list,
                    gridSize: Math.round(16 * window.devicePixelRatio),
                    weightFactor: fontSize => fontSize,
                    fontFamily: 'SimHei, Arial',
                    color: () => ['#007BFF', '#28A745', '#DC3545'][cluster.cluster_id % 3],
                    rotateRatio: 0.2
                });
            });

            // 渲染散点图
            renderScatterPlot(embeddings.doc_ids, embeddings.coordinates, embeddings.labels);

        })
        .catch(err => {
            overlay.style.display = "none";
            console.error("请求失败:", err);
            document.getElementById("cluster-results").innerHTML = "<p>加载失败，请刷新页面重试。</p>";
        });
}



// 绘制柱状图
function renderBarChart(clusters) {
    const chartContainer = document.getElementById("bar-chart");
    const clusterLabels = clusters.map(c => `类 ${c.cluster_id}`);
    const docCounts = clusters.map(c => c.size);

    const chart = echarts.init(chartContainer);
    const option = {
        title: {
            text: "各聚类文档数量统计",
            left: "center"
        },
        tooltip: {
            trigger: "axis",
            axisPointer: { type: "shadow" }
        },
        xAxis: {
            type: "category",
            data: clusterLabels,
            axisLabel: { rotate: 45 }
        },
        yAxis: { type: "value", name: "文档数量" },
        series: [{
            name: "文档数量",
            type: "bar",
            data: docCounts,
            itemStyle: { color: "#007BFF" }
        }],
        grid: { left: "10%", right: "10%", bottom: "15%", top: "20%" }
    };
    chart.setOption(option);
}

function renderScatterPlot(doc_ids, coordinates, labels) {
    // 构建数据结构：每个 label 是一个独立的系列
    const seriesMap = {};
    const categoryIndices = [...new Set(labels)].sort(); // 去重并排序

    doc_ids.forEach((id, i) => {
        const label = labels[i];
        if (!seriesMap[label]) {
            seriesMap[label] = [];
        }
        seriesMap[label].push({
            name: id,
            value: [coordinates[i][0], coordinates[i][1]],
            category: `类 ${label}`
        });
    });

    // 构造 color 映射表（支持最多 20 类）
    const colorList = [
        '#007BFF', '#28A745', '#DC3545', '#FFC107', '#6F42C1',
        '#FD7E14', '#20C997', '#664DFF', '#FF8300', '#1E9493',
        '#ADB5BD', '#E83E8C', '#664DFF', '#4E79A7', '#F28E2B',
        '#E15759', '#76B7B2', '#59A2BE', '#EDC948', '#B07AA1',
        '#FFAE42', '#0066CC', '#009933', '#CC0000', '#CCCC00',
        '#660099', '#FF6600', '#00CC99', '#006666', '#993300',
        '#FF99CC', '#99CC00', '#666666', '#FFCCFF', '#999900',
        '#0099CC', '#FF6666', '#00CCFF', '#9900CC', '#FF9900',
        '#006600', '#990000', '#CCCCFF', '#666600', '#003366',
        '#996633', '#FF99FF', '#009999', '#9999FF', '#000080'
    ];


    // 构造 ECharts 的 series 数组
    const series = categoryIndices.map(label => ({
        name: `类 ${label}`,
        type: 'scatter',
        symbolSize: 10,
        data: seriesMap[label],
        emphasis: {
            itemStyle: { borderWidth: 1, borderColor: '#000' }
        },
        itemStyle: {
            color: colorList[label % colorList.length]
        }
    }));

    // 初始化图表
    const chartContainer = document.getElementById("scatter-chart");
    const scatterChart = echarts.init(chartContainer);

    const option = {
        title: {
            text: 'TF-IDF 向量降维可视化',
            left: 'center'
        },
        tooltip: {
            trigger: 'item',
            formatter: function(params) {
                return `${params.seriesName}<br/>文档ID: ${params.data.name}`;
            }
        },
        legend: {
            data: categoryIndices.map(c => `类 ${c}`),
            bottom: 10,
            type: 'scroll', // 支持滚动条
            pageIconSize: 12,
            itemGap: 5,
            formatter: name => name, // 显示完整名称
            width: '80%' // 宽度自适应
        },
        xAxis: {},
        yAxis: {},
        series: series,
        grid: { left: "5%", right: "5%", bottom: "15%" }
    };

    scatterChart.setOption(option, true); // true 表示合并配置
}





// 页面加载完成后调用
loadClusterResults();

</script>
</body>
</html>
